//
//  CLDispatchCenter.m
//  ComponentLinkDemo
//
//  Created by wenchao on 17/3/16.
//  Copyright © 2017年 zhenby. All rights reserved.
//

#import "CLDispatchCenter.h"
#import "CLPSafeMutableDictionary.h"

@interface CLDispatchInfo : NSObject

@property (nonatomic,weak) id target;
@property (nonatomic,assign) SEL selector;

@end

@implementation CLDispatchInfo

@end

@interface CLDispatchCenter ()

@property (nonatomic,strong) CLPSafeMutableDictionary*  itemMap;

@end

@implementation CLDispatchCenter

+ (instancetype)defaultCenter
{
    static CLDispatchCenter* instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _itemMap = [[CLPSafeMutableDictionary alloc] init];
    }
    return self;
}

- (id)send:(NSString*)type parameters:(NSDictionary*)params
{
    CLDispatchInfo* info = [self.itemMap objectForKey:type];
    if (!info) {
        return nil;
    }
    
    if (info && info.target && [info.target respondsToSelector:info.selector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        return [info.target performSelector:info.selector withObject:params];
#pragma clang diagnostic pop
    }
    
    return nil;
}

- (BOOL)registerType:(NSString*)type target:(id)target method:(SEL)selector
{
    NSAssert(type && target && selector, @"parameters can not be nil");
    CLDispatchInfo* info = [CLDispatchInfo new];
    info.target = target;
    info.selector = selector;
    
    if (![self.itemMap objectForKey:type]) {
        [self.itemMap setObject:info forKey:type];
        return YES;
    }
    
    return YES;
}

- (BOOL)unRegisterType:(NSString*)type
{
    if ([self.itemMap objectForKey:type]) {
        [self.itemMap removeObjectForKey:type];
    }
    return YES;
}

- (BOOL)unRegisterTarget:(id)target
{
    __block NSMutableArray* keys = [NSMutableArray array];
    [self.itemMap enumerateKeysAndObjectsUsingBlock:^(NSString*  _Nonnull key, CLDispatchInfo*  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj isEqual:target]) {
            [keys addObject:key];
        }
    }];
    
    if (keys.count > 0) {
        [self.itemMap removeObjectsForKeys:keys];
    }
    
    return YES;
}

+ (id)send:(NSString*)type parameters:(NSDictionary*)params
{
    return [[CLDispatchCenter defaultCenter] send:type parameters:params];
}

+ (BOOL)registerType:(NSString*)type target:(id)target method:(SEL)selector
{
    return [[CLDispatchCenter defaultCenter] registerType:type target:target method:selector];
}

+ (BOOL)unRegisterType:(NSString*)type
{
    return [[CLDispatchCenter defaultCenter] unRegisterType:type];
}

+ (BOOL)unRegisterTarget:(id)target
{
    return [[CLDispatchCenter defaultCenter] unRegisterTarget:target];
}

@end
